package com.wtj.security.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wtj.security.domain.LoginUser;
import com.wtj.user.domain.User;
import com.wtj.user.mapper.MenuMapper;
import com.wtj.user.mapper.UserMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *  1.配置UserDetailsService实现类
 *  2.配置LoginUser
 *  3.使用我们数据库初始化的用户访问 http://localhost:8080/user/page?pageNum=1&pageSize=1
 *  4.登录，并成功访问
 *  5.配置密码加密器
 *  原因：SpringSecurity默认使用的PasswordEncoder要求数据库中的密码格式为：{加密方式密码。对应的就是
 *  {n00p}123456,实际表示的是123456
 *  但是我们在数据库直接暴露123456为密码，会造成安全问题，所以我们需要把加密后的1234的密文当作密码，此
 *  时用户在浏览器登录时输入1234，我们如何确保用户能够登录进去呢，答案是SpringSecurity默认的密码校验，替
 *  换为SpringSecurity,为我们提供的BCryptPasswordEncoder
 *  6.配置BCryptPasswordEncoder,创建Spring的配置类 extends WebSecurityConfigurerAdapter
 */
@Service
public class MyUserDetailServiceImpl implements UserDetailsService {
    @Resource
    private UserMapper  userMapper;
    @Resource
    private MenuMapper menuMapper;

    /**
     *  从数据库获取用户的信息，封装为LoginUser对象
     * @param userName
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        //1.构建查询条件
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName,userName);
        //2.查询用户数据
        User user = userMapper.selectOne(queryWrapper);
        //3.判断用户是否存在，不存在抛出异常
        if (user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        //4.封装用户权限信息
        //自定义权限信息，后续引入RBAC后从数据库获取
        // TODO：注意这里更改后需要重新登录，否则Redis中存储的用户信息为之前的数据
        List<String> list = menuMapper.selectPermsByUserId(user.getId());

        //4.封装用户信息
        return new LoginUser(user,list);
    }
}
